package com.ruoyi.framework.logger;


import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.framework.web.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 日志切面处理类
 *
 */
@Aspect
@Order(5)
@Component
@Slf4j
public class WebLogAspect {

    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Autowired
    private TokenService tokenService;

    @Pointcut("execution(public * com.ruoyi.web.controller..*Controller.*(..))")
    public void webLog() {
    }
    

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        startTime.set(System.currentTimeMillis());

        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            // 设置请求的seqNo 
            // 设置请求的seqNo 
            String seqNo = String.valueOf(System.currentTimeMillis());
            Object[] args = joinPoint.getArgs();
/*            for (Object arg : args) {
            	  BaseRequest<?> baseReq = null;
                  if(arg != null && arg instanceof BaseRequest) {
                      baseReq = (BaseRequest<?>) arg;
                      seqNo = baseReq.getSeqNo();
                      break;
                  }
              }*/
            request.setAttribute("seqNo", seqNo);


            //String logUid = MDC.get(LogConstant.TRACE_ID);

            String traceId =TraceIdUtil.getTraceId();
            MDC.put(LogConstant.TRACE_ID, traceId);
            request.setAttribute("traceId", traceId);

            LoginUser loginUser = tokenService.getLoginUser(request);

            // 记录下请求内容
            log.info("traceId:{},URL:{},HTTP_METHOD:{},CLASS_METHOD:{},IP:{},USER:{},ARGS:{}",
                    traceId,
                    request.getRequestURL().toString(),
                    request.getMethod(),
                    joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName(),
                    request.getRemoteAddr(),
                    loginUser != null ? loginUser.getUserId()+"/"+loginUser.getUsername()+"/"+loginUser.getDeptId(): null,
                    Arrays.toString(joinPoint.getArgs())
            );

            //log.info("LOG_UID:{},REQ_SEQ_NO:{}",logUid,request.getAttribute("seqNo"));
        }

    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String seqNo = null;
        String traceId =null;
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            //seqNo = String.valueOf(request.getAttribute("seqNo"));
            traceId =  String.valueOf(request.getAttribute("traceId"));
        }
         
        // 处理完请求，返回内容
        long diffTime = System.currentTimeMillis() - startTime.get();
        //log.info("traceId:{},RESPONSE:{},SPEND TIME : {}ms",traceId,ret,diffTime);
        // Response 数据过多 . 默认关闭
        log.info("traceId:{},SPEND TIME : {}ms",traceId,diffTime);

        startTime.remove();
    }

    @AfterThrowing(pointcut = "webLog()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String seqNo = null;
        String traceId =null;
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            //seqNo = String.valueOf(request.getAttribute("seqNo"));
            traceId =  String.valueOf(request.getAttribute("traceId"));
        }
        log.error("traceId:{},EXCEPTION IN {}.{},EXCEPTION INFO",
                traceId,
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(),
                e
        );
        startTime.remove();
    }

}
